package com.ssy.lingxi.order.serviceimpl.base;

import cn.hutool.core.util.StrUtil;
import com.ssy.lingxi.common.response.ResponseCode;
import com.ssy.lingxi.common.response.Wrapper;
import com.ssy.lingxi.order.entity.OrderConsigneeDO;
import com.ssy.lingxi.order.entity.OrderDO;
import com.ssy.lingxi.order.entity.OrderProductDO;
import com.ssy.lingxi.order.model.bo.LogisticsProductBO;
import com.ssy.lingxi.order.model.bo.LogisticsProductDetailBO;
import com.ssy.lingxi.order.model.dto.CountryAreaDTO;
import com.ssy.lingxi.order.model.dto.OrderConsigneeDTO;
import com.ssy.lingxi.order.model.dto.SupplyProductDTO;
import com.ssy.lingxi.order.model.vo.basic.request.BuyerOrderConsigneeVO;
import com.ssy.lingxi.order.model.vo.basic.request.OrderConsigneeVO;
import com.ssy.lingxi.order.model.vo.basic.response.DeliveryConsigneeDetailVO;
import com.ssy.lingxi.order.model.vo.basic.response.OrderConsigneeDetailVO;
import com.ssy.lingxi.order.repository.CountryAreaRepository;
import com.ssy.lingxi.order.repository.OrderConsigneeRepository;
import com.ssy.lingxi.order.service.base.IBaseOrderConsigneeService;
import com.ssy.lingxi.order.service.feign.ILogisticsFeignService;
import com.ssy.lingxi.order.utils.NumberUtil;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 订单收货人信息相关接口实现类
 * @author 万宁
 * @version 2.0.0
 * @date 2021-07-19
 */
@Service
public class BaseOrderConsigneeServiceImpl implements IBaseOrderConsigneeService {
    @Resource
    private ILogisticsFeignService logisticsFeignService;

    @Resource
    private CountryAreaRepository countryAreaRepository;

    @Resource
    private OrderConsigneeRepository orderConsigneeRepository;

    /**
     * 校验并生成订单收货人信息
     *
     * @param order       订单
     * @param consigneeVO 订单收货人接口参数
     * @param isCreate 是否新增，true-新增，false-修改
     * @return 订单收货人
     */
    @Override
    public Wrapper<Void> checkOrderConsignee(OrderDO order, OrderConsigneeVO consigneeVO, boolean isCreate) {
        if(!isCreate) {
            orderConsigneeRepository.deleteByOrder(order);
        }

        if(Objects.isNull(consigneeVO)) {
            order.setConsignee(null);
            return Wrapper.success();
        }

        List<String> areaCodeList = Stream.of(consigneeVO.getProvinceCode(), consigneeVO.getCityCode(), consigneeVO.getDistrictCode(), consigneeVO.getStreetCode()).collect(Collectors.toList());
        List<CountryAreaDTO> areaList = countryAreaRepository.findByCodeIn(areaCodeList, CountryAreaDTO.class);
        String provinceName = areaList.stream().filter(area -> area.getCode().equals(consigneeVO.getProvinceCode())).map(CountryAreaDTO::getName).findFirst().orElse(null);
        if(!StringUtils.hasLength(provinceName)) {
            return Wrapper.fail(ResponseCode.ORDER_PROVINCE_DOES_NOT_EXIST);
        }

        String cityName = areaList.stream().filter(area -> area.getCode().equals(consigneeVO.getCityCode())).map(CountryAreaDTO::getName).findFirst().orElse(null);
        if(!StringUtils.hasLength(cityName)) {
            return Wrapper.fail(ResponseCode.ORDER_CITY_DOES_NOT_EXIST);
        }

        String districtName = areaList.stream().filter(area -> area.getCode().equals(consigneeVO.getDistrictCode())).map(CountryAreaDTO::getName).findFirst().orElse(null);
        if(!StringUtils.hasLength(districtName)) {
            return Wrapper.fail(ResponseCode.ORDER_DISTRICT_DOES_NOT_EXIST);
        }

        String streetName = "";
        if(StringUtils.hasLength(consigneeVO.getStreetCode())) {
            streetName = areaList.stream().filter(area -> area.getCode().equals(consigneeVO.getStreetCode())).map(CountryAreaDTO::getName).findFirst().orElse(null);
        }

        OrderConsigneeDO consignee = new OrderConsigneeDO();
        consignee.setOrder(order);
        consignee.setConsigneeId(consigneeVO.getConsigneeId());
        consignee.setConsignee(consigneeVO.getConsignee());
        consignee.setProvinceCode(consigneeVO.getProvinceCode());
        consignee.setProvinceName(provinceName);
        consignee.setCityCode(consigneeVO.getCityCode());
        consignee.setCityName(cityName);
        consignee.setDistrictCode(consigneeVO.getDistrictCode());
        consignee.setDistrictName(districtName);
        consignee.setStreetCode(StrUtil.isEmpty(consigneeVO.getStreetCode()) ? "" : consigneeVO.getStreetCode());
        consignee.setStreetName(streetName);
        consignee.setAddress(consigneeVO.getAddress());
        consignee.setPostalCode(StringUtils.hasLength(consigneeVO.getPostalCode()) ? consigneeVO.getPostalCode().trim() : "");
        consignee.setCountryCode(consigneeVO.getCountryCode());
        consignee.setPhone(consigneeVO.getPhone());
        consignee.setTelephone(StringUtils.hasLength(consigneeVO.getTelephone()) ? consigneeVO.getTelephone().trim() : consigneeVO.getTelephone());
        consignee.setDefaultConsignee(consigneeVO.getDefaultConsignee());
        order.setConsignee(consignee);

        return Wrapper.success();
    }

    /**
     * 校验并生成订单收货人信息
     *
     * @param order       订单
     * @param consigneeVO 订单收货人接口参数
     * @param isCreate    是否新增，true-新增，false-修改
     * @return 操作结果
     */
    @Override
    public Wrapper<Void> checkPurchaseOrderConsignee(OrderDO order, BuyerOrderConsigneeVO consigneeVO, boolean isCreate) {
        if(!isCreate) {
            orderConsigneeRepository.deleteByOrder(order);
        }

        if(Objects.isNull(consigneeVO)) {
            order.setConsignee(null);
            return Wrapper.success();
        }

        List<String> areaCodeList = Stream.of(consigneeVO.getProvinceCode(), consigneeVO.getCityCode(), consigneeVO.getDistrictCode(), consigneeVO.getStreetCode()).collect(Collectors.toList());
        List<CountryAreaDTO> areaList = countryAreaRepository.findByCodeIn(areaCodeList, CountryAreaDTO.class);
        String provinceName = areaList.stream().filter(area -> area.getCode().equals(consigneeVO.getProvinceCode())).map(CountryAreaDTO::getName).findFirst().orElse(null);
        if(!StringUtils.hasLength(provinceName)) {
            return Wrapper.fail(ResponseCode.ORDER_PROVINCE_DOES_NOT_EXIST);
        }

        String cityName = areaList.stream().filter(area -> area.getCode().equals(consigneeVO.getCityCode())).map(CountryAreaDTO::getName).findFirst().orElse(null);
        if(!StringUtils.hasLength(cityName)) {
            return Wrapper.fail(ResponseCode.ORDER_CITY_DOES_NOT_EXIST);
        }

        String districtName = areaList.stream().filter(area -> area.getCode().equals(consigneeVO.getDistrictCode())).map(CountryAreaDTO::getName).findFirst().orElse(null);
        if(!StringUtils.hasLength(districtName)) {
            return Wrapper.fail(ResponseCode.ORDER_DISTRICT_DOES_NOT_EXIST);
        }

        String streetName = "";
        if(StringUtils.hasLength(consigneeVO.getStreetCode())) {
            streetName = areaList.stream().filter(area -> area.getCode().equals(consigneeVO.getStreetCode())).map(CountryAreaDTO::getName).findFirst().orElse(null);
        }

        OrderConsigneeDO consignee = new OrderConsigneeDO();
        consignee.setOrder(order);
        consignee.setConsigneeId(consigneeVO.getConsigneeId());
        consignee.setConsignee(consigneeVO.getConsignee());
        consignee.setProvinceCode(consigneeVO.getProvinceCode());
        consignee.setProvinceName(provinceName);
        consignee.setCityCode(consigneeVO.getCityCode());
        consignee.setCityName(cityName);
        consignee.setDistrictCode(consigneeVO.getDistrictCode());
        consignee.setDistrictName(districtName);
        consignee.setStreetCode(StrUtil.isEmpty(consigneeVO.getStreetCode()) ? "" : consigneeVO.getStreetCode());
        consignee.setStreetName(streetName);
        consignee.setAddress(consigneeVO.getAddress());
        consignee.setPostalCode(StringUtils.hasLength(consigneeVO.getPostalCode()) ? consigneeVO.getPostalCode().trim() : "");
        consignee.setCountryCode(consigneeVO.getCountryCode());
        consignee.setPhone(consigneeVO.getPhone());
        consignee.setTelephone(StringUtils.hasLength(consigneeVO.getTelephone()) ? consigneeVO.getTelephone().trim() : consigneeVO.getTelephone());
        consignee.setDefaultConsignee(consigneeVO.getDefaultConsignee());
        order.setConsignee(consignee);

        return Wrapper.success();
    }

    /**
     * （转单） - 生成供应商收货人信息，计算订单运费
     *
     * @param orders         转单前的订单列表
     * @param orderProducts  转单前的订单商品列表
     * @param supplyProducts 上级供应商商品列表
     * @return 转单订单的收货人信息列表
     */
    @Override
    public Wrapper<List<OrderConsigneeDTO>> findVendorConsignees(List<OrderDO> orders, List<OrderProductDO> orderProducts, List<SupplyProductDTO> supplyProducts) {
        //Step 1: 构造查询参数
        List<LogisticsProductBO> logisticsProducts = new ArrayList<>();
        for (OrderDO order : orders.stream().filter(order -> Objects.nonNull(order.getConsignee())).collect(Collectors.toList())) {
            List<LogisticsProductDetailBO> productDetails = new ArrayList<>();
            for (OrderProductDO orderProduct : orderProducts.stream().filter(p -> p.getOrder().getId().equals(order.getId())).collect(Collectors.toList())) {
                SupplyProductDTO supplyProduct = supplyProducts.stream().filter(p -> p.getVendorSkuId().equals(orderProduct.getSkuId())).findFirst().orElse(null);
                if(supplyProduct == null || NumberUtil.isNullOrZero(supplyProduct.getLogisticsTemplateId())) {
                    continue;
                }

                LogisticsProductDetailBO detailBO = new LogisticsProductDetailBO();
                detailBO.setTemplateId(supplyProduct.getLogisticsTemplateId());
                detailBO.setQuantity(orderProduct.getQuantity());
                detailBO.setWeight(supplyProduct.getWeight());
                productDetails.add(detailBO);
            }

            LogisticsProductBO productBO = new LogisticsProductBO();
            productBO.setOrderId(order.getId());
            productBO.setConsigneeId(order.getConsignee().getConsigneeId());
            productBO.setVendorMemberId(order.getVendorMemberId());
            productBO.setVendorRoleId(order.getVendorRoleId());
            productBO.setSupplyProducts(productDetails);
            logisticsProducts.add(productBO);
        }

        if(CollectionUtils.isEmpty(logisticsProducts)) {
            return Wrapper.success(new ArrayList<>());
        }

        //Step 2: 从物流服务新增供应商的收货人信息，计算运费
        Wrapper<List<OrderConsigneeDTO>> logisticsResult = logisticsFeignService.findVendorConsignee(logisticsProducts);
        if(logisticsResult.getCode() != ResponseCode.SUCCESS.getCode()) {
            return Wrapper.fail(logisticsResult.getCode(), logisticsResult.getMessage());
        }

        //Step 3: 填充交付日期，返回
        return Wrapper.success(logisticsResult.getData());
    }

    /**
     * （转单） - 校验并生成转单订单收货人信息
     *
     * @param order        转单订单
     * @param consigneeDTO 物流服务返回的收货人信息
     * @return 操作结果
     */
    @Override
    public Wrapper<Void> transferOrderConsignee(OrderDO order, OrderConsigneeDTO consigneeDTO) {
        if(Objects.isNull(consigneeDTO)) {
            order.setConsignee(null);
            return Wrapper.success();
        }

        OrderConsigneeDO consignee = new OrderConsigneeDO();
        consignee.setOrder(order);
        consignee.setConsigneeId(consigneeDTO.getConsigneeId());
        consignee.setConsignee(consigneeDTO.getConsignee());
        consignee.setProvinceCode(consigneeDTO.getProvinceCode());
        consignee.setProvinceName(consigneeDTO.getProvinceName());
        consignee.setCityCode(consigneeDTO.getCityCode());
        consignee.setCityName(consigneeDTO.getCityName());
        consignee.setDistrictCode(consigneeDTO.getDistrictCode());
        consignee.setDistrictName(consigneeDTO.getDistrictName());
        consignee.setStreetCode(StrUtil.isEmpty(consigneeDTO.getStreetCode()) ? "" : consigneeDTO.getStreetCode());
        consignee.setStreetName(StrUtil.isEmpty(consigneeDTO.getStreetName()) ? "" : consigneeDTO.getStreetName());
        consignee.setAddress(consigneeDTO.getAddress());
        consignee.setPostalCode(consigneeDTO.getPostalCode());
        consignee.setCountryCode(consigneeDTO.getCountryCode());
        consignee.setPhone(consigneeDTO.getPhone());
        consignee.setTelephone(consigneeDTO.getTelephone());
        consignee.setDefaultConsignee(consigneeDTO.getDefaultConsignee());
        order.setConsignee(consignee);

        return Wrapper.success();
    }

    /**
     * 查询订单交付人信息
     *
     * @param order 订单
     * @return 订单收货人信息
     */
    @Override
    public OrderConsigneeDetailVO getOrderConsignee(OrderDO order) {
        OrderConsigneeDetailVO detailVO = new OrderConsigneeDetailVO(order.getDeliverPeriod());
        OrderConsigneeDO consigneeDO = orderConsigneeRepository.findFirstByOrder(order);
        if(consigneeDO == null) {
            return detailVO;
        }

        detailVO.setConsigneeId(consigneeDO.getConsigneeId());
        detailVO.setConsignee(consigneeDO.getConsignee());
        detailVO.setAreaName(orderConsigneeToArea(consigneeDO));
        detailVO.setProvinceCode(consigneeDO.getProvinceCode());
        detailVO.setCityCode(consigneeDO.getCityCode());
        detailVO.setDistrictCode(consigneeDO.getDistrictCode());
        detailVO.setStreetCode(consigneeDO.getStreetCode());
        detailVO.setAddress(consigneeDO.getAddress());
        detailVO.setCountryCode(consigneeDO.getCountryCode());
        detailVO.setPhone(consigneeDO.getPhone());
        detailVO.setDefaultConsignee(consigneeDO.getDefaultConsignee());
        return detailVO;
    }

    /**
     * 订单收货地址转字符串地址
     * @param consignee 订单收货人信息
     * @return 拼接后的字符串-地址+收货人+电话
     */
    @Override
    public String orderConsigneeToString(OrderConsigneeDO consignee) {
        if (consignee == null) {
            return "";
        }

        String provinceName = StringUtils.hasLength(consignee.getProvinceName()) ? consignee.getProvinceName() : "";
        String cityName = StringUtils.hasLength(consignee.getCityName()) ? consignee.getCityName() : "";
        String districtName = StringUtils.hasLength(consignee.getDistrictName()) ? consignee.getDistrictName() : "";
        String streetName = StringUtils.hasLength(consignee.getStreetName()) ? consignee.getStreetName() : "";
        String address = StringUtils.hasLength(consignee.getAddress()) ? consignee.getAddress() : "";
        String receiver = StringUtils.hasLength(consignee.getConsignee()) ? consignee.getConsignee() : "";
        String phone = StringUtils.hasLength(consignee.getPhone()) ? consignee.getPhone() : "";
        return provinceName + cityName + districtName + streetName + address + "  " + receiver + "  " + phone;
    }

    /**
     * 订单收货地址转字符串地址
     * @param consignee 订单收货人信息
     * @return 拼接后的字符串-省市区街道
     */
    @Override
    public String orderConsigneeToArea(OrderConsigneeDO consignee) {
        if (consignee == null) {
            return "";
        }
        String provinceName = consignee.getProvinceName() == null ? "" : consignee.getProvinceName();
        String cityName = consignee.getCityName() == null ? "" : consignee.getCityName();
        String districtName = consignee.getDistrictName() == null ? "" : consignee.getDistrictName();
        String streetName = consignee.getStreetName() == null ? "" : consignee.getStreetName();
        return provinceName + cityName + districtName + streetName;
    }

    /**
     * 销售发货单-根据订单id查询收货人信息
     * @param orderId 订单id
     * @return 订单收货人信息
     */
    @Override
    public DeliveryConsigneeDetailVO getOrderConsignee(Long orderId) {
        DeliveryConsigneeDetailVO detailVO = new DeliveryConsigneeDetailVO();
        OrderConsigneeDO consignee = orderConsigneeRepository.findFirstByOrderId(orderId);
        if (consignee == null) {
            return detailVO;
        }

        detailVO.setConsigneeId(consignee.getConsigneeId());
        detailVO.setConsignee(consignee.getConsignee());
        detailVO.setAreaName(orderConsigneeToArea(consignee));
        detailVO.setProvinceCode(consignee.getProvinceCode());
        detailVO.setCityCode(consignee.getCityCode());
        detailVO.setDistrictCode(consignee.getDistrictCode());
        detailVO.setStreetCode(consignee.getStreetCode());
        detailVO.setAddress(consignee.getAddress());
        detailVO.setCountryCode(consignee.getCountryCode());
        detailVO.setPhone(consignee.getPhone());
        return detailVO;
    }
}
